import { ElMessage } from 'element-plus'
import { useEventbus } from '@/hooks/useEventBus.js'

let socket = null
let isConnent = false
let reConnectNum = 0

// 心跳 20s一次，防止长时间不交互后台断开
let heartCheck = {
  heartbeatData: {
    heart: `发送心跳信息~ ${new Date()}`,
  },
  timeout: 20 * 1000,
  heartbeat: null,
  start: function () {
    this.heartbeat = setInterval(() => {
      if (isConnent) {
        webSocketSend(this.heartbeatData)
      } else {
        this.clear()
      }
    }, this.timeout)
  },
  reset: function () {
    clearInterval(this.heartbeat)
    this.start()
  },
  clear: function () {
    clearInterval(this.heartbeat)
  },
}

// 初始化连接
const initWebSocket = (wsURL, callback) => {
  if ('WebSocket' in window) {
    socket = new WebSocket(wsURL)
  } else {
    ElMessage({
      message: '浏览器不支持webSocket!',
      type: 'warning',
    })
    return
  }
  socket.onopen = function () {
    webSocketOnOpen(callback)
  }
  socket.onmessage = function (e) {
    webSocketOnMessage(e)
  }
  socket.onclose = function (e) {
    webSocketOnClose(e)
  }
  socket.onerror = function (e) {
    webSocketOnError(e)
  }
}

// socket链接
const webSocketOnOpen = (callback) => {
  console.log('[socket] 连接成功')
  isConnent = true
  heartCheck.start()
  reConnectNum = 0
  callback()
}

// 收到消息推送
const webSocketOnMessage = (e) => {
  console.log('[socket] 收到推送消息', e)
  const eventBus = useEventbus()
  // 消息推送至总线触发器，交由总线触发器进行分类触发
  eventBus.emitterHighaway(e)
}

// 监听关闭事件
const webSocketOnClose = (e) => {
  heartCheck.clear()
  isConnent = false
  console.log('[socket] 关闭连接')
  if (e.code == 1006) {
    if (reConnectNum < 3) {
      initWebSocket()
      ++reConnectNum
    } else {
      ElMessage({
        message: 'webSocket无法连接,清刷新页面重试',
        type: 'warning',
      })
    }
  }
}

// 监听错误事件
const webSocketOnError = (e) => {
  heartCheck.clear()
  isConnent = false
  console.log('[socket] 连接发生错误', e)
}

// 发送数据
const webSocketSend = (data) => {
  socket.send(JSON.stringify(data))
}

// 主动关闭
const closeWebSocket = (e) => {
  socket.close()
  heartCheck.clear()
  isConnent = false
  reConnectNum = 0
}

// 判断socket连接状态
const sendSocket = (agenData, callback) => {
  switch (socket.readyState) {
    case socket.CONNECTING:
      setTimeout(() => {
        sendSocket(agenData, callback)
      }, 1000)
      break
    case socket.OPEN:
      webSocketSend(agenData)
      break
    case socket.CLOSING:
      setTimeout(() => {
        sendSocket(agenData, callback)
      }, 1000)
      break
    case socket.CLOSED:
      break
    default:
      break
  }
}

export function useWebsocket() {
  return {
    initWebSocket,
    webSocketSend,
    closeWebSocket,
    sendSocket,
  }
}
